package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.leanring.LearningLessonDTO;
import com.tianji.api.dto.leanring.LearningRecordDTO;
import com.tianji.api.dto.leanring.LearningRecordFormDTO;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.exceptions.DbException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.po.LearningRecord;
import com.tianji.learning.enums.LessonStatus;
import com.tianji.learning.enums.SectionType;
import com.tianji.learning.mapper.LearningRecordMapper;
import com.tianji.learning.service.ILearningLessonService;
import com.tianji.learning.service.ILearningRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

/**
 * <p>
 * 学习记录表 服务实现类
 * </p>
 *
 * @author 邓明明
 * @since 2023-04-24
 */
@Service
public class LearningRecordServiceImpl extends ServiceImpl<LearningRecordMapper, LearningRecord> implements ILearningRecordService {

    @Resource
    private ILearningLessonService lessonService;
    @Resource
    private CourseClient courseClient;

    @Override
    public LearningLessonDTO queryLearningRecordByCourse(Long courseId) {
        // 获取登陆用户id
        Long userId = UserContext.getUser();
        // 根据userId和courseId(课程id是公用的)查询课表
        LearningLesson learningLesson = lessonService.queryByUserIdAndCourseId(userId,courseId);
        if (learningLesson == null) {
            return null;
        }
        // 查询学习记录
        List<LearningRecord> records = lambdaQuery()
                .eq(LearningRecord::getLessonId, learningLesson.getId()).list();
        // 把records转成学习课表进度信息DTO
        List<LearningRecordDTO> recordDTOS = BeanUtils.copyList(records, LearningRecordDTO.class);
        // 封装结果
        LearningLessonDTO lessonDTO = new LearningLessonDTO();
        lessonDTO.setId(learningLesson.getId());
        // 最近一次学习的小节id
        lessonDTO.setLatestSectionId(learningLesson.getLatestSectionId());
        lessonDTO.setRecords(recordDTOS);

        return lessonDTO;
    }

    @Override
    @Transactional
    public void addLearningRecord(LearningRecordFormDTO recordFormDTO) {
        // 1、首先获取当前登录用户
        Long userId = UserContext.getUser();
        // 2、处理学习记录
        // 要先定义一个布尔变量，来确定该视频或者考试是否学习完成了
        boolean finished = false;
        // 判断当前学习的是视频还是考试
        if (recordFormDTO.getSectionType() == SectionType.VIDEO.getValue()) {
            // 当前学习是视频
            finished = handleVideoRecord(userId,recordFormDTO);
        } else {
            // 当前学习是考试
            finished = handleExamRecord(userId,recordFormDTO);
        }
        // 3、最后处理课表数据
        handleLearningLessonChanges(recordFormDTO,finished);
    }

    private void handleLearningLessonChanges(LearningRecordFormDTO recordFormDTO, boolean finished) {
        // 查询课表
        LearningLesson lesson = lessonService.getById(recordFormDTO.getLessonId());
        if (lesson == null) {
            throw new BizIllegalException("课程不存在，无法更新数据！");
        }
        // 判断是否有新完成的小节
        boolean allLearned = false;
        if (finished) {
            // 如果有新完成的小节，得出课表的小结总数以及已学完总数
            CourseFullInfoDTO courseInfoById =
                    courseClient.getCourseInfoById(lesson.getCourseId(), false, false);
            if (courseInfoById == null) {
                throw new BizIllegalException("课程不存在，无法更新数据！");
            }
            // 比较课程是否已学习完成数量是否大于总课程数 量
            allLearned = lesson.getLearnedSections() + 1 > courseInfoById.getSectionNum();
        }
        // 更新课表
        lessonService.lambdaUpdate()
                .set(allLearned,LearningLesson::getStatus, LessonStatus.FINISHED.getValue())
                .set(!finished,LearningLesson::getLatestSectionId,recordFormDTO.getSectionId())
                .set(allLearned,LearningLesson::getLatestLearnTime, recordFormDTO.getCommitTime())
                .set(lesson.getLearnedSections() == 0,LearningLesson::getStatus, LessonStatus.LEARNING.getValue())
                .setSql(finished,"learned_sections = learn_sections + 1")
                .eq(LearningLesson::getId,lesson.getId())
                .update();


    }

    private boolean handleExamRecord(Long userId, LearningRecordFormDTO recordFormDTO) {
        // 如果是考试视频，则直接新增数据就行了
        // 新增进数据库的数据是LearningRecord，所以要转成LearningRecordVO
        LearningRecord learningRecord = BeanUtils.copyBean(recordFormDTO, LearningRecord.class);
        // 填充数据
        learningRecord.setUserId(userId);
        learningRecord.setFinished(true);
        learningRecord.setFinishTime(recordFormDTO.getCommitTime());
        // 新增进数据库
        boolean result = this.save(learningRecord);
        if (!result) {
            throw new DbException("新增考试记录失败！");
        }
        return true;
    }

    private boolean handleVideoRecord(Long userId, LearningRecordFormDTO recordFormDTO) {
        // 处理视频
        // 查询当前学习视频记录
        LearningRecord oldLearningRecord = lambdaQuery().eq(LearningRecord::getLessonId, recordFormDTO.getLessonId())
                .eq(LearningRecord::getSectionId, recordFormDTO.getSectionId())
                .one();
        // 1、判断当前学习视频记录是否存在
        if (oldLearningRecord == null) {
            // 如果不存在，则新增,基于心跳模式，所以第一次播放肯定返回一个false，不会是已学完
            // 如果是考试视频，则直接新增数据就行了
            // 新增进数据库的数据是LearningRecord，所以要转成LearningRecordVO
            LearningRecord learningRecord = BeanUtils.copyBean(recordFormDTO, LearningRecord.class);
            // 填充数据
            learningRecord.setUserId(userId);
            // 新增进数据库
            boolean result = this.save(learningRecord);
            if (!result) {
                throw new DbException("新增学习记录失败！");
            }
            return false;
        }

        // 如果存在，则更新
        // 判断是否是第一次完成:必须是当前状态为false未完成，并且，视频播放长度百分比大于百分之50
        boolean finished = !oldLearningRecord.getFinished() && recordFormDTO.getMoment() * 2 >= recordFormDTO.getDuration();
        // 更新数据
        boolean result = lambdaUpdate().set(LearningRecord::getMoment, recordFormDTO.getMoment())
                .set(finished, LearningRecord::getFinished, true)
                .set(finished, LearningRecord::getFinishTime, recordFormDTO.getCommitTime())
                .eq(LearningRecord::getId, oldLearningRecord.getId())
                .update();
        if (!result) {
            throw new DbException("更新学习记录失败！");
        }
        return finished;
    }
}
